package org.example;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 * the type of ${PROJECT_NAME}
 *
 * <p>
 * .
 *
 * @author 铁甲小宝
 */
public class NettyDemo {

    public static void main(String[] args) {

        byteBufferJianDanDuXie();

        zhanBaoHeBanBao();

        testFileChanel();

        testFileChanelPlus();

    }

    /**
     * FileChanel 传输数据 > 2g
     */
    private static void testFileChanelPlus() {
        try (FileInputStream fileInputStream = new FileInputStream("data.txt");
             FileOutputStream fileOutputStream = new FileOutputStream("data-out-plus.txt")) {
            FileChannel channel = fileInputStream.getChannel();
            for (long left = channel.size(); left > 0; ) {
                left -= channel.transferTo(0, channel.size(), fileOutputStream.getChannel());
                System.out.println("循环： " + left + "/" + channel.size());
            }

        } catch (IOException e) {
            e.getStackTrace();
        }
    }

    /**
     * FileChanel 传输数据 <= 2g
     */
    private static void testFileChanel() {
        try (FileInputStream fileInputStream = new FileInputStream("data.txt");
             FileOutputStream fileOutputStream = new FileOutputStream("data-out.txt")) {
            FileChannel channel = fileInputStream.getChannel();
            channel.transferTo(0, channel.size(), fileOutputStream.getChannel());
        } catch (IOException e) {
            e.getStackTrace();
        }
    }

    /**
     * bytebuffer简单读写demo
     */
    private static void byteBufferJianDanDuXie() {
        // 获取数据通道
        try (FileChannel fileChannel = new FileInputStream("data.txt").getChannel()) {
            // 准备缓冲区, 大小是固定的不能动态调整
            ByteBuffer byteBuffer = ByteBuffer.allocate(10);
            while (true) {
                // 从 channel 读取数据，向 bytebuffer 写入
                int read = fileChannel.read(byteBuffer);
                if (read == -1) {
                    break;
                }
                // 切换至读模式
                byteBuffer.flip();
                // 是否还有剩余读未读数据
                while (byteBuffer.hasRemaining()) {
                    byte b = byteBuffer.get();
                    System.out.println(b + "  " + (char) b);
                }
                // 切换至写模式，会压缩未读的数据
                byteBuffer.compact();

                // 切换至写模式，不会压缩未读的数据
//                byteBuffer.clear();


                // bytebuffer 与 String 互转
                ByteBuffer encode = StandardCharsets.UTF_8.encode("hello你好");
                String decode = StandardCharsets.UTF_8.decode(encode).toString();
                System.out.println("decode = " + decode);

                ByteBuffer buffer = ByteBuffer.wrap("哈喽helll".getBytes());
                String decode2 = StandardCharsets.UTF_8.decode(buffer).toString();
                System.out.println("decode2 = " + decode2);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * bytebuffer黏包与半包
     */
    private static void zhanBaoHeBanBao() {
        // randomAccessFile 获取管道
        try (RandomAccessFile randomAccessFile = new RandomAccessFile("data.txt", "r")) {
            FileChannel channel = randomAccessFile.getChannel();
            ByteBuffer allocate = ByteBuffer.allocate(512);
            channel.read(allocate);
            allocate.flip();
            System.out.println("StandardCharsets.UTF_8.decode(allocate).toString() = " + StandardCharsets.UTF_8.decode(allocate).toString());

            // 黏包与半包
            ByteBuffer buffer = ByteBuffer.allocate(32);
            buffer.put("How are \nyou.\nI".getBytes());
            buffer.put("'m fine\n".getBytes());
            buffer.flip();
            int spit = -1;
            for (int i = 0; i < buffer.limit(); i++) {
                byte b = buffer.get(i);
                if (b == '\n') {
                    int length = i - spit;
                    ByteBuffer b1 = ByteBuffer.allocate(length);
                    for (int i1 = spit + 1; i1 < spit + length; i1++) {
                        b1.put(buffer.get(i1));
                    }
                    b1.flip();
                    System.out.println(StandardCharsets.UTF_8.decode(b1).toString());
                    spit = i;
                }
            }
            buffer.compact();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}